/*
 * Copyright 2012 XueSong Guo.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.webwheel;

import cn.webwheel.results.EmptyResult;
import cn.webwheel.results.JSonResult;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Default main class.<br/>
 * Handling exception occurred while action method executing.<br/>
 */
public class DefaultMain extends Main {

    /**
     * Wrap exception to a json object and return it to client.
     * <p>
     * <b>json object format:</b><br/>
     * <p><blockquote><pre>
     *     {
     *         "msg": "the exception's message",
     *         "stackTrace":[
     *             "exception's stack trace1",
     *             "exception's stack trace2",
     *             "exception's stack trace3",
     *             ....
     *         ]
     *     }
     * </pre></blockquote></p>
     */
    public static Object executeActionError(WebContext ctx, ActionInfo ai, Object action, Throwable e) throws Throwable {
        if (e instanceof LogicException) {
            return ((LogicException) e).getResult();
        }
        Logger.getLogger(DefaultMain.class.getName()).log(Level.SEVERE, "action execution error", e);
        StringBuilder sb = new StringBuilder();
        sb.append("{\n");
        String s;
        try {
            s = JSonResult.objectMapper.writeValueAsString(e.toString());
        } catch (IOException e1) {
            s = "\"" + e.toString().replace("\"", "'") + "\"";
        }
        sb.append("    \"msg\" : " + s + ",\n");
        sb.append("    \"stackTrace\" : [");
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw));
        String[] ss = sw.toString().split("\r\n");
        for (int i = 1; i < ss.length; i++) {
            if (sb.charAt(sb.length() - 1) != '[') {
                sb.append(',');
            }
            sb.append("\n        \"").append(ss[i]).append('"');
        }
        sb.append("\n    ]\n");
        sb.append("}");
        HttpServletResponse response = ctx.getResponse();
        if (JSonResult.defWrapMultipart && ServletFileUpload.isMultipartContent(ctx.getRequest()) && !"XMLHttpRequest".equals(ctx.getRequest().getHeader("X-Requested-With"))) {
            response.setContentType("text/html");
            sb.insert(0, "<textarea>\n");
            sb.append("\n</textarea>");
        } else {
            response.setContentType("application/json");
        }
        response.setCharacterEncoding("utf-8");
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Expires", "-1");
        response.getWriter().write(sb.toString());
        return EmptyResult.inst;
    }

    /**
     * If exception occurred, call {@link #executeActionError(WebContext, ActionInfo, Object, Throwable)}
     */
    @Override
    protected Object executeAction(WebContext ctx, ActionInfo ai, Object action) throws Throwable {
        try {
            return super.executeAction(ctx, ai, action);
        } catch (Throwable e) {
            return executeActionError(ctx, ai, action, e);
        }
    }
}
